package de.dhbw.karlsruhe.picsim.model.decode;

import de.dhbw.karlsruhe.picsim.model.commands.PicInstruction;
import de.dhbw.karlsruhe.picsim.model.commands.impl.*;
import de.dhbw.karlsruhe.picsim.model.memory.OpCode;
import de.dhbw.karlsruhe.picsim.util.Bits;
import de.dhbw.karlsruhe.picsim.util.impl.BitUtilities;
import org.jetbrains.annotations.NotNull;

/**
 * Created by IntelliJ IDEA.
 * User: goesen
 * Date: Apr 12, 2010
 * Time: 4:09:53 PM
 */

final class ByteOrientatedDecoder implements Decoder {

    @SuppressWarnings({"OverlyComplexBooleanExpression"})
    @NotNull
    @Override
    public PicInstruction decode(@NotNull final OpCode opCode) {
        final Bits bits = opCode.getValue();
        final Boolean targetIsWRegister = !bits.isSet(7);
        final Bits argument = BitUtilities.subBits(bits, 0, 7);

        //Prüfung auf diejenigen die mit Null anfangen
        if (!bits.isSet(11)) {
            if (bits.isSet(10) && bits.isSet(9) && bits.isSet(8)) {
                return new AddWF(targetIsWRegister, argument);
            } else if (bits.isSet(10) && !bits.isSet(9) && bits.isSet(8)) {
                return new AndWF(targetIsWRegister, argument);
            } else if (!bits.isSet(10) && !bits.isSet(9) && bits.isSet(8) && targetIsWRegister) {
                return new ClrW(argument);
            } else if (!bits.isSet(10) && !bits.isSet(9) && bits.isSet(8) && !targetIsWRegister) {
                return new ClrF(argument);
            } else if (!bits.isSet(10) && bits.isSet(9) && bits.isSet(8)) {
                return new DecF(targetIsWRegister, argument);
            } else if (bits.isSet(10) && !bits.isSet(9) && !bits.isSet(7)) {
                return new IorWF(targetIsWRegister, argument);
            } else if (!bits.isSet(10) && !bits.isSet(9) && !bits.isSet(8) && !targetIsWRegister) {
                return new MovWF(argument);
            } else if (!bits.isSet(10) && bits.isSet(9) && !bits.isSet(8)) {
                return new SubWF(targetIsWRegister, argument);
            } else if (!bits.isSet(10) && !bits.isSet(9) && !bits.isSet(8)) {
                return new NoOperation();
            } else if (bits.isSet(10) && bits.isSet(9) && !bits.isSet(8)) {
                return new XorWF(targetIsWRegister, argument);
            }
            throw new IllegalArgumentException();
        }
        //Prüfung auf diejenigen die mit Eins anfangen
        else {
            if (!bits.isSet(10) && !bits.isSet(9) && bits.isSet(8)) {
                return new ComF(targetIsWRegister, argument);
            } else if (!bits.isSet(10) && bits.isSet(9) && bits.isSet(8)) {
                return new DecFSZ(argument, targetIsWRegister);
            } else if (!bits.isSet(10) && bits.isSet(9) && !bits.isSet(8)) {
                return new IncF(targetIsWRegister, argument);
            } else if (bits.isSet(10) && bits.isSet(9) && bits.isSet(8)) {
                return new IncFSZ(argument, targetIsWRegister);
            } else if (!bits.isSet(10) && !bits.isSet(9) && !bits.isSet(8)) {
                return new MovF(targetIsWRegister, argument);
            } else if (bits.isSet(10) && !bits.isSet(9) && bits.isSet(8)) {
                return new RotateLeft(targetIsWRegister, argument);
            } else if (bits.isSet(10) && !bits.isSet(9) && !bits.isSet(8)) {
                return new RotateRight(argument, targetIsWRegister);
            } else if (bits.isSet(10) && bits.isSet(9) && !bits.isSet(8)) {
                return new SwapF(argument, targetIsWRegister);
            }

        }


        return null;
    }
}
